package com.adjy.pathbuilders.world;

import org.jbox2d.collision.AABB;
import org.jbox2d.common.Vec2;

import android.graphics.Bitmap;
import android.graphics.Canvas;

import com.adjy.pathbuilders.objects.GameEntityType;
import com.adjy.pathbuilders.physics.PhysicalObject;
import com.adjy.pathbuilders.rendering.AnimationPack;
import com.adjy.pathbuilders.rendering.GameCanvas;
import com.adjy.pathbuilders.rendering.Renderable;

/**
 * GameEntity class holds all information for a basic Entity in the game
 */
public abstract class GameEntity extends PhysicalObject implements Renderable {
	
	private GameEntityType type;
	private boolean dead;
	private AnimationPack animationPack;
	private String currentAnimationID;
	private float renderXOffset = 0, renderYOffset = 0;

	/**
	 * Creates a Entity of our Game
	 * 
	 * @param type
	 *            GameEntityType of this new Entity
	 * @param x
	 *            X Position of this Entity
	 * @param y
	 *            Y Position of this Entity
	 * @param width
	 *            Width of the Entity
	 * @param height
	 *            Height of the Entity
	 */
	public GameEntity(GameEntityType type, float x, float y, float width, float height, AnimationPack ap) {
		this(type, x, y, width, height, ap, true);
	}

	/**
	 * Creates a Entity of our Game
	 * 
	 * @param type
	 *            GameEntityType of this new Entity
	 * @param x
	 *            X Position of this Entity
	 * @param y
	 *            Y Position of this Entity
	 * @param width
	 *            Width of the Entity
	 * @param height
	 *            Height of the Entity
	 * @param gravity
	 *            True - Enable Gravity for this Entity<br>
	 *            False - Disable Gravity for this Entity
	 */
	public GameEntity(GameEntityType type, float x, float y, float width, float height, AnimationPack ap, boolean gravity) {
		this(type, x, y, width, height, ap, gravity, true, false);
	}

	/**
	 * Creates a Entity of our Game
	 * 
	 * @param type
	 *            GameEntityType of this new Entity
	 * @param x
	 *            X Position of this Entity
	 * @param y
	 *            Y Position of this Entity
	 * @param width
	 *            Width of the Entity
	 * @param height
	 *            Height of the Entity
	 * @param gravity
	 *            True - Enable Gravity for this Entity<br>
	 *            False - Disable Gravity for this Entity
	 * @param collidable
	 *            True - Enable Collisions for this Entity<br>
	 *            False - Disable Collisions for this Entity
	 * @param dynamic
	 *            True - This Entity changes its position<br>
	 *            False - This Entity doesn't change position
	 */
	public GameEntity(GameEntityType type, float x, float y, float width, float height, AnimationPack ap, boolean gravity, boolean collidable, boolean dynamic) {
		super(x, y, width, height, gravity, collidable, dynamic);
		this.type = type;
		this.dead = false;
		this.animationPack = ap;
	}
	
	public AnimationPack getAnimationPack() {
		return this.animationPack;
	}

	/**
	 * Renders the entity
	 * 
	 * @param canvas
	 *            Canvas to be drawn on
	 */
	public void render(GameCanvas canvas, float timeElapsed) {
		
		if (getBody() != null) {
			Vec2 position = getBody().getPosition();
			Bitmap bitmap = animationPack.getAnimation(currentAnimationID).getCurrentFrame(timeElapsed);
			
			canvas.getCanvas().save(Canvas.MATRIX_SAVE_FLAG);
			canvas.rotate((float) (180 * - getBody().getAngle() / Math.PI), position.x + renderXOffset, position.y + renderYOffset);
			canvas.drawBitmapFromPhysics(bitmap,
					renderXOffset + position.x - getWidth() / 2,
					renderYOffset + position.y + getHeight() / 2);
			canvas.getCanvas().restore();
		} else {
			canvas.drawBitmapFromPhysics(
					getAnimationPack().
					getAnimation(currentAnimationID).
					getCurrentFrame(timeElapsed),
					getCenter().x + renderXOffset - getWidth() / 2,
					getCenter().y + renderYOffset + getHeight() / 2);
		}
		
	}
	
	
	public void setAnimation(String animationID) {
		this.currentAnimationID = animationID;
	}
	
	/**
	 * Gets the Type of this GameEntity
	 * 
	 * @return GameEntityType
	 */
	public GameEntityType getType() {
		return type;
	}

	/**
	 * Checks if this Entity is Dead
	 * 
	 * @return True - Unit is Dead<br>
	 *         False - Unit is Alive
	 */
	public boolean isDead() {
		return dead;
	}

	/**
	 * Kills this Entity
	 */
	public void kill() {
		dead = true;
	}
	
	public void setRenderOffsets(float x, float y) {
		this.renderXOffset = x;
		this.renderYOffset = y;
	}
	
	public AABB getVirtualAABB() {
		return new AABB(
				new Vec2(getCenter().x + renderXOffset - getWidth() / 2, getCenter().y + renderYOffset - getHeight() / 2),
				new Vec2(getCenter().x + renderXOffset + getWidth() / 2, getCenter().y + renderYOffset + getHeight() / 2));
	}

}
